package com.huanletao.httpclient;

import com.huanletao.json.JacksonUtils;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.*;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.net.URIBuilder;
import org.apache.hc.core5.util.Timeout;

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * apache HttpClient example；
 *
 */
public class ApacheHttpClientExample {

    /**
     * create HttpClient example ;
     */
    public void createHttpClient() {
        // 此种方式可以在创建时 设置一些默认值
        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultHeaders(Collections.emptyList())   // 设置默认请求头
                .setDefaultRequestConfig(RequestConfig.DEFAULT)  // 设置默认配置
                .build();
        //create default HttpClient；
        CloseableHttpClient aDefault = HttpClients.createDefault();

        //create system httpClient;
        CloseableHttpClient system = HttpClients.createSystem();
    }

    /**
     * configuration requestconfig；
     *
     * @return
     */
    public RequestConfig configurationRequestConfig() {
        //  创建请求配置信息
        RequestConfig requestConfig = RequestConfig.custom()
                // 设置连接超时时间
                .setConnectTimeout(Timeout.of(3000, TimeUnit.MILLISECONDS))
                // 设置响应超时时间
                .setResponseTimeout(3000, TimeUnit.MILLISECONDS)
                // 设置从连接池获取链接的超时时间
                .setConnectionRequestTimeout(3000, TimeUnit.MILLISECONDS)
                .build();
        return requestConfig;
    }

    /**
     * 配置全局参数；
     */
    public void configGlobalInfo() {
        // 此种方式可以在创建时 设置一些默认值
        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultHeaders(Collections.emptyList())   // 设置默认请求头
                .setDefaultRequestConfig(configurationRequestConfig())  // 设置默认配置
                .build();
    }

    /**
     *
     */
    public void buildRequestExample() throws IOException {
        // 创建 GET 请求对象
        HttpGet httpGet = new HttpGet("uri");
        // 设置请求参数
        httpGet.setConfig(null);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        httpClient.execute(httpGet);
    }

    /**
     *
     */
    public void buildGlobalHeadersExample() {
        List<Header> headers = new ArrayList<>();
        headers.add(new BasicHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON));
        headers.add(new BasicHeader(HttpHeaders.ACCEPT_ENCODING, "gzip, x-gzip, deflate"));
        headers.add(new BasicHeader(HttpHeaders.CONNECTION, "keep-alive"));
        // 创建 一个默认的 httpClient
        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultHeaders(headers)   // 设置默认请求头
                .build();
    }

    /**
     *
     */
    public void buildSingleRequestHeadersExample() {
        // 创建 POST 请求
        HttpPost httpPost = new HttpPost("uri");
        // 添加 Content-Type 请求头
        httpPost.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED);
        // 添加 accept 请求头
        httpPost.addHeader(new BasicHeader(HttpHeaders.ACCEPT, "*/*"));
    }


    public void getRequestExample() throws IOException, ParseException {
        String name = URLEncoder.encode("张三", "utf-8");
        // 请求路径及参数
        String url = "http://localhost:10010/user/params?age=20&name=" + name;

        // 创建 GET 请求对象
        HttpGet httpGet = new HttpGet(url);
        // 调用 HttpClient 的 execute 方法执行请求

        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpGet);
        // 获取请求状态
        int code = response.getCode();
        // 如果请求成功
        if (code == HttpStatus.SC_OK) {
            System.out.println("code = " + EntityUtils.toString(response.getEntity()));
        }
    }

    /**
     * @throws URISyntaxException
     * @throws IOException
     * @throws ParseException
     */
    public void getRequestExample2() throws URISyntaxException, IOException, ParseException {
        // 构建请求路径，及参数
        URL url = new URL("http://localhost:10010/user/params");
        URI uri = new URIBuilder()
                .setScheme(url.getProtocol())
                .setHost(url.getHost())
                .setPort(url.getPort())
                .setPath(url.getPath())
                // 构建参数
                .setParameters(
                        new BasicNameValuePair("name", "张三"),
                        new BasicNameValuePair("age", "20")
                ).build();

        // 创建 GET 请求对象
        HttpGet httpGet = new HttpGet(uri);
        // 调用 HttpClient 的 execute 方法执行请求
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpGet);
        // 获取请求状态
        int code = response.getCode();
        // 如果请求成功
        if (code == HttpStatus.SC_OK) {
            System.out.println("响应结果为：{}" + EntityUtils.toString(response.getEntity()));
        }

    }

    /**
     *
     * @throws IOException
     */
    public void postRequestExampleJson() throws IOException {
        // 请求参数
        String url = "http://localhost:10010/user/body";
        // 创建 GET 请求对象
        HttpPost httpPost = new HttpPost(url);
        // 构建对象
        User user = new User();
        user.setName("张三")
                .setAge(20)
                .setAddress(new Address()
                        .setCounty("中国")
                        .setCity("北京"))
                .setAihao(Arrays.asList("跑步", "爬山", "看书"));

        // 创建 字符串实体对象
        HttpEntity httpEntity = new StringEntity(JacksonUtils.toJSONString(user));
        httpPost.setEntity(httpEntity);
        // 发送 POST 请求
        CloseableHttpClient httpClient = HttpClients.createDefault();
        httpClient.execute(httpPost);
        //修改 创建 ContentType 对象为 form 表单模式
        ContentType contentType = ContentType.create("application/x-www-form-urlencoded", StandardCharsets.UTF_8);
        // 添加到 HttpPost 头中
        httpPost.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
    }


    /**
     *
     * @throws IOException
     * @throws ParseException
     */
    public void uploadFileExample() throws IOException, ParseException {
        //要上传的文件
        File file = new File("F:/20150703212056_Yxi4L.jpeg");
        // 创建对象
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        // 添加二进制消息体
        builder.addBinaryBody("file", file);
        // 也可以添加文本消息
        ContentType contentType = ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8);
        builder.addTextBody("name", "张三", contentType);
        // 通过 MultipartEntityBuilder 构建消息体
        HttpEntity httpEntity = builder.build();
        HttpPost httpPost = new HttpPost("http://localhost:10010/user/upload");
        httpPost.setEntity(httpEntity);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpPost);
        // 获取请求状态
        int code = response.getCode();
        // 如果请求成功
        if(code == HttpStatus.SC_OK){
            System.out.println("响应结果为：{}"+ EntityUtils.toString(response.getEntity()));
        }

    }

    /**
     *
     * @throws Exception
     */
    public void downloadFileExample() throws Exception {
        // 请求下载路径
        HttpGet httpGet = new HttpGet("http://localhost:10010/user/downLoad");
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpGet);

        // 如果请求成功
        if (response.getCode() == HttpStatus.SC_OK){

            // 获取下载文件的文件名，此处的 File-Name 头信息，需要在服务端进行自定义
            Header header = response.getFirstHeader("File-Name");
            String value = header.getValue();

            // 读取数据
            byte[] bytes = EntityUtils.toByteArray(response.getEntity());
            try (OutputStream outputStream = new FileOutputStream("F:/" + value);){
                outputStream.write(bytes);
                outputStream.flush();
            }
        }
    }
}
